package com.army.serverless;

import com.huawei.agconnect.function.AGCFunctionException;
import com.huawei.agconnect.function.AGConnectFunction;
import com.huawei.agconnect.function.FunctionResult;
import com.huawei.hmf.tasks.HarmonyTask;
import com.huawei.hmf.tasks.OnHarmonyCompleteListener;
import ohos.aafwk.ability.Ability;
import ohos.aafwk.content.Intent;
import ohos.rpc.*;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;
import ohos.utils.zson.ZSONObject;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 计算十二生肖服务类
 */
public class ZodiacServiceAbility extends Ability {
    private static final HiLogLabel LABEL_LOG = new HiLogLabel(3, 0xD001100, "ZodiacService");
    // 云函数
    private AGConnectFunction function;

    private MyRemote remote = new MyRemote();

    // FA在请求PA服务时会调用Ability.connectAbility连接PA，连接成功后，需要在onConnect返回一个remote对象，供FA向PA发送消息
    @Override
    protected IRemoteObject onConnect(Intent intent) {
        super.onConnect(intent);
        return remote.asObject();
    }

    /**
     * 内部类
     */
    class MyRemote extends RemoteObject implements IRemoteBroker {
        private static final int SUCCESS = 0;
        private static final int ERROR = 1;
        private static final int PLUS = 1001;
        private static final int SUBSCRIBE  = 1005;
        private static final int UNSUBSCRIBE  = 1006;

        private IRemoteObject remoteObjectHandler;
//        private Thread thread = null;
        private int year = -1;
        private String born = "?";

        /**
         * 构造方法
         */
        public MyRemote() {
            super("MyService_MyRemote");
        }

        @Override
        public boolean onRemoteRequest(int code, MessageParcel data, MessageParcel reply, MessageOption option) throws RemoteException {
            // code是eTS传参messageCode
            switch (code) {
                case PLUS: {
                    // 2. 接收到前端传过来的参数
                    HiLog.info(LABEL_LOG, "xx Java计算生肖-开始");
                    // 读取参数数据
                    String dataStr = data.readString();
                    HiLog.info(LABEL_LOG, "xx Java读取参数" + dataStr);
                    Map<String, Object> param = new HashMap<>();
                    try {
                        // 把读取到字符串参数转为Map对象
                        param = ZSONObject.stringToClass(dataStr, Map.class);
                        // 从对象中获取参数年份, 并赋值为全局变量，给订阅事件使用
                        year = Integer.parseInt( String.valueOf(param.get("year")));
                        HiLog.info(LABEL_LOG, "xx Java获取到年份是： " + year);
                    }catch (RuntimeException e) {
                        HiLog.error(LABEL_LOG, "xx Java转换数据失败.");
                    }

//                    // Java计算十二生肖
//                    born = getBornFromJava(year);
//                    HiLog.info(LABEL_LOG, "xx Java计算出生肖是: " + born);

                    // Serverless计算十二生肖,异步请求，这里先返回调用成功，然后通过订阅事件获取异步结果
                    // 赋值和默认值一样
                    born = "?";

                    // 返回结果当前仅支持String，对于复杂结构可以序列化为ZSON字符串上报
                    Map<String, Object> result = new HashMap<>();
                    result.put("code", SUCCESS);
                    result.put("abilityResult", born);
                    reply.writeString(ZSONObject.toZSONString(result));

                    // 调用云函数是异步请求，这里直接返回成功，在订阅事件再调用云函数计算生肖
                    HiLog.info(LABEL_LOG, "xx Java计算生肖-结束");
                    break;
                }
                case SUBSCRIBE: {
                    // 4. 开始后端订阅事件
                    HiLog.info(LABEL_LOG, "xx Java订阅事件-开始");
                    remoteObjectHandler = data.readRemoteObject();
                    //封装调用云函数为一个方法
                    getBornFromServerless();
                    Map<String, Object> result = new HashMap<String, Object>();
                    result.put("code", SUCCESS);
                    // 返回订阅成功，但还没有计算出生肖
                    reply.writeString(ZSONObject.toZSONString(result));
                    HiLog.info(LABEL_LOG, "xx Java订阅事件-结束");
                    break;
                }
                case UNSUBSCRIBE: {
                    // 取消订阅事件
                    HiLog.info(LABEL_LOG, "xx Java取消订阅-开始");
                    remoteObjectHandler = null;
                    Map<String, Object> result = new HashMap<String, Object>();
                    result.put("code", SUCCESS);
                    reply.writeString(ZSONObject.toZSONString(result));
                    HiLog.info(LABEL_LOG, "xx Java取消订阅-结束");
                    break;
                }
                default: {
                    Map<String, Object> result = new HashMap<>();
                    result.put("code", ERROR);
                    result.put("abilityError", "服务器繁忙, 请稍后再试!!!");
                    reply.writeString(ZSONObject.toZSONString(result));
                    return false;
                }
            }

            return true;
        }

        /**
        * Serverless计算十二生肖
        */
        private void getBornFromServerless() {
            // 5. 真正到了云函数出场了
            HiLog.info(LABEL_LOG, "xx Java参数：" + year);
            HashMap<String, String> map = new HashMap();
            map.put("year", year + "");

            function.wrap("test-zodiac-$latest").call(map)
                    .addOnCompleteListener(new OnHarmonyCompleteListener<FunctionResult>() {
                        @Override
                        public void onComplete(HarmonyTask<FunctionResult> task) {
                            if (task.isSuccessful()) {
                                // 云函数返回的生肖结果
                                String value = task.getResult().getValue();
                                HiLog.info(LABEL_LOG, "xxx Java云函数返回生肖: " + value);
                                born = value;

                                MessageParcel data = MessageParcel.obtain();
                                MessageParcel reply = MessageParcel.obtain();
                                MessageOption option = new MessageOption();
                                Map<String, Object> result = new HashMap<>();
                                result.put("code", SUCCESS);
                                result.put("abilityResult", born);
                                data.writeString(ZSONObject.toZSONString(result));
                                try {
                                    // 7. 通过发送请求数据，在前端回调函数接收结果
                                    remoteObjectHandler.sendRequest(100, data, reply, option);
                                } catch (RemoteException e) {
                                    HiLog.error(LABEL_LOG, "xx Java发送事件失败: " + e.getMessage());
                                    e.printStackTrace();
                                }
                            } else {
                                Exception e = task.getException();
                                if (e instanceof AGCFunctionException) {
                                    AGCFunctionException functionException = (AGCFunctionException) e;
                                    int errCode = functionException.getCode();
                                    String message = functionException.getMessage();
                                    HiLog.info(LABEL_LOG, "xxx Java ErrCode: " + errCode + ", Message:  " + message);
                                }
                            }
                        }
                    });
        }

        @Override
        public IRemoteObject asObject() {
            return this;
        }
    }



    private String[] zodiac = {"猴", "鸡", "狗", "猪", "鼠", "牛", "虎", "兔", "龙", "蛇", "马", "羊"};

    /**
     * Java计算十二生肖
     * @param year
     * @return
     */
    private String getBornFromJava(int year) {
        if (year == -1) { return "不是有效年份"; }
        int idx = year % 12;
        return zodiac[idx];
    }

    @Override
    public void onStart(Intent intent) {
        HiLog.error(LABEL_LOG, "ZodiacServiceAbility::onStart");
        super.onStart(intent);
        // 云函数
        function = AGConnectFunction.getInstance();
    }

    @Override
    public void onBackground() {
        super.onBackground();
        HiLog.info(LABEL_LOG, "ZodiacServiceAbility::onBackground");
    }

    @Override
    public void onStop() {
        super.onStop();
        HiLog.info(LABEL_LOG, "ZodiacServiceAbility::onStop");
    }

    @Override
    public void onCommand(Intent intent, boolean restart, int startId) {
    }

    @Override
    public void onDisconnect(Intent intent) {
    }
}